package com.pisolution.scheduler.core.tuple;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintWriter;

/**
 * 用于生成存储临时数据的元组.
 *
 * @author sora
 * @version 0.1.0
 */
public class TupleGenerator {
    /** 类存储根路径. */
    private static final String ROOT_DIRECTORY = "./pi-scheduler-core/src/main/java";

    /** 元组类包名. */
    private static final String PACKAGE = "com.pisolution.scheduler.core.tuple";

    /** 元组类泛型标识. */
    private static final String GEN_TYPE_PREFIX = "T";

    // -------------------------------------------------------------------------------------------------

    /** 需要生成的元组中最低的字段数量. */
    private static final int FIRST_TUPLE_INDEX = 2;

    /** 需要生成的元祖中最高的字段数量. */
    private static final int LAST_TUPLE_INDEX = 7;

    // -------------------------------------------------------------------------------------------------
    //  生成入口
    // -------------------------------------------------------------------------------------------------

    public static void main(String[] args) throws Exception {
        createTupleClass(new File(ROOT_DIRECTORY));
    }

    // -------------------------------------------------------------------------------------------------
    //  辅助方法 (构造)
    // -------------------------------------------------------------------------------------------------

    /**
     * 创建元组类.
     *
     * @param root 类生成后存储的路径.
     *
     * @throws FileNotFoundException 如果无法访问生成目录.
     */
    private static void createTupleClass(File root) throws FileNotFoundException {
        // 1. 确认元组类生成后的存储路径.
        File tuplePackage = getPackage(root);

        // 2. 如果该路径不存在则创建该路径.
        if (!tuplePackage.exists()) {
            // noinspection ResultOfMethodCallIgnored - the result is useless.
            tuplePackage.mkdirs();
        }

        // 3. 生成元组类.
        for (int index = FIRST_TUPLE_INDEX; index <= LAST_TUPLE_INDEX; index++) {
            PrintWriter writer = new PrintWriter(new File(tuplePackage, "Tuple" + index + ".java"));

            writeTupleClass(writer, index);

            writer.flush();
            writer.close();
        }
    }

    /**
     * 生成指定数量的元组类.
     *
     * @param writer 用于生成元组类.
     * @param numFields 元组的数量.
     */
    private static void writeTupleClass(final PrintWriter writer, final int numFields) {
        final String className = "Tuple" + numFields;

        // 1. 输出包名.
        writer.println("package " + PACKAGE + ';');
        writer.println();

        // 2. 输出类注释.
        writer.println("/**");
        writer.println(
            " * 用于存储临时对象的" + convertNum(numFields) + "元组. "
        );
        writer.println(" *");

        for (int index = 1; index <= numFields; index++) {
            writer.println(" * @param <" + GEN_TYPE_PREFIX + index + "> 元组中第" + convertNum(index) + "个字段值的类型.");
        }

        writer.println(" *");
        writer.println(" * @author sora");
        writer.println(" * @version 0.1.0");
        writer.println(" */");

        // 3. 生成类名.
        writer.println("@SuppressWarnings(\"unused\")");
        writer.print("public final class " + className + "<");

        for (int index = 1; index <= numFields; index++) {
            if (index > 1) {
                writer.print(", ");
            }

            writer.print(GEN_TYPE_PREFIX + index);
        }

        writer.println("> {");

        // 4. 生成元组字段.
        for (int index = 1; index <= numFields; index++) {
            writer.println("    /** 元组中第" + convertNum(index) + "个字段. */");
            writer.println("    public " + GEN_TYPE_PREFIX + index + " field" + index + ';');
            writer.println();
        }

        // 5. 生成构造函数.
        writer.println(
            "    // -------------------------------------------------------------------------------------------------"
        );
        writer.println("    //  初始化");
        writer.println(
            "    // -------------------------------------------------------------------------------------------------"
        );
        writer.println();

        // 5.1. 生成参数列表.
        StringBuilder paramList = new StringBuilder("(");
        for (int index = 1; index <= numFields; index++) {
            if (index > 1) {
                paramList.append(", ");
            }

            paramList.append(GEN_TYPE_PREFIX).append(index).append(" field").append(index);
        }
        paramList.append(")");

        // 5.2. 生成函数体.
        writer.println("    /**");
        writer.println("     * 以指定的值创建一个新的元组实例.");
        writer.println("     *");

        for (int index = 1; index <= numFields; index++) {
            writer.println("     * @param field" + index + " 第" + convertNum(index) + "个元组字段的值.");
        }

        writer.println("     */");
        writer.println("    public " + className + paramList.toString() + " {");

        for (int index = 1; index <= numFields; index++) {
            writer.println("        this.field" + index + " = field" + index + ';');
        }

        writer.println("    }");
        writer.println("}");
    }

    /**
     * 组合类存储根路径与包名以获取元组类生成后的存储路径.
     *
     * @param root 类存储根路径.
     *
     * @return 元组类实际存储路径.
     */
    private static File getPackage(File root) {
        File directory = new File(root, PACKAGE.replace('.', '/'));

        if (!directory.exists() && directory.isDirectory()) {
            System.err.println("none existent directory: " + directory.getAbsolutePath());
            System.exit(1);
        }

        return directory;
    }

    /**
     * 将给定数字转换为汉字形式.
     *
     * @param index 需要转换的数字.
     *
     * @return 转换后的汉字.
     */
    private static String convertNum(final int index) {
        return "一,二,三,四,五,六,七".split(",")[index - 1];
    }
}
